package cn.wolfcode.web.controller;

import cn.wolfcode.common.domain.UserInfo;
import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.common.web.anno.RequireLogin;
import cn.wolfcode.domain.OrderInfo;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMessage;
import cn.wolfcode.redis.CommonRedisKey;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.UserUtil;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.apache.commons.lang.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ConcurrentHashMap;


@RestController
@RequestMapping("/order")
@Slf4j
public class OrderInfoController {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private IOrderInfoService orderInfoService;

    public static ConcurrentHashMap<Long, Boolean> stockOverTag = new ConcurrentHashMap<>();

    @GetMapping("/find")
    @RequireLogin
    public Result<OrderInfo> find(String orderNo, HttpServletRequest request) {
        // 判断orderNo是否为空
        if (StringUtils.isEmpty(orderNo)) {
            throw new BusinessException(SeckillCodeMsg.OPT_ERROR);
        }
        OrderInfo orderInfo = orderInfoService.get(orderNo);
        // 判断是否是伪造订单id
        if (orderInfo == null) {
            throw new BusinessException(SeckillCodeMsg.OPT_ERROR);
        }
        String token = request.getHeader("token");
        UserInfo user = UserUtil.getUser(redisTemplate, token);
        // 用户只能看自己的订单信息
        if (!orderInfo.getUserId().equals(user.getPhone())) {
            throw new BusinessException(SeckillCodeMsg.OPT_ERROR);
        }
        return Result.success(orderInfo);
    }


    @PostMapping("/doSeckill")
    // 登录拦截
    @RequireLogin
    public Result<String> doSeckill(int time, Long seckillId, HttpServletRequest request) {
        // 参数校验
        if (StringUtils.isEmpty(time + "") || seckillId == null) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_ERROR);
        }
        SeckillProductVo vo = seckillProductService.find(time, seckillId);
        // 判断是否在秒杀时间内
        /*if (!DateUtil.isLegalTime(vo.getStartDate(), time)) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_TIME_OUT);
        }*/
        // 本地标志判断, 减少请求进入redis
        Boolean isFlag = stockOverTag.get(seckillId);
        if (isFlag != null && isFlag) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }

        // 重复下单判断
        String token = request.getHeader("token");
        UserInfo userInfo = UserUtil.getUser(redisTemplate, token);
        Long phone = userInfo.getPhone();
        String orderSetRealKey = SeckillRedisKey.SECKILL_ORDER_SET.getRealKey(phone.toString());
        Boolean member = redisTemplate.opsForSet().isMember(orderSetRealKey, seckillId.toString());
        if (member) {
            throw new BusinessException(SeckillCodeMsg.REPEAT_SECKILL);
        }

        // redis库存判断  减少请求进入服务层
        // 获取redis中的库存
        String countKey = SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time + "");
        Integer count = Integer.parseInt((String) redisTemplate.opsForHash().get(countKey, seckillId + ""));
        if (count == null || count <= 0) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }
        // redis库存 - 1
        redisTemplate.opsForHash().increment(countKey,seckillId + "",-1);
        if (count - 1 == 0) {
            stockOverTag.put(seckillId, true);
        }
        // 发送消息
        OrderMessage message = new OrderMessage();
        message.setSeckillId(seckillId);
        message.setTime(time);
        message.setToken(token);
        message.setUserPhone(phone);
        rocketMQTemplate.sendOneWay(MQConstant.ORDER_PEDDING_TOPIC,message);

        return Result.success("正在抢购中,请稍等...");
    }
}
